package main

import (
	"context"
	"flag"
	"github.com/golang/glog"
	"net"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	flag.Set("v", "4")
	flag.Parse()
	defer glog.Flush()
	glog.Info("Starting http server..")
	port := os.Getenv("httpport")
	glog.Info("port is :", port)
	mux := http.NewServeMux()
	mux.HandleFunc("/", rootHandler)
	mux.HandleFunc("/healthz", healthz)

	server := &http.Server{Addr: ":" + port, Handler: mux}

	go func() {
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			glog.Fatalf("Starting http server failed:%s", err)
		}
	}()
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
	<-sig

	glog.Info("Http server shutting down...")
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := server.Shutdown(ctx); err != nil {
		glog.Info("error occured when shutting down http server:", err)
	}
	glog.Info("shutting down http server successfully")
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	//3.Server 端记录访问日志包括客户端 IP，HTTP 返回码，输出到 server 端的标准输出
	defer func() {
		statusCode := 200
		err := recover()
		if err != nil {
			statusCode = 500
		}
		w.WriteHeader(statusCode)
		glog.Infof("client ip: %s,http status code: %d", RmoteIp(r), statusCode)
	}()
	//1.将 request 中带的 header 写入 response header
	for k, values := range r.Header {
		for _, v := range values {
			w.Header().Add(k, v)
		}
	}

	//2.读取当前系统的环境变量中的 VERSION 配置，并写入 response header
	version := os.Getenv("VERSION")
	w.Header().Add("version", version)

}

func healthz(w http.ResponseWriter, r *http.Request) {
	//4.当访问 localhost/healthz 时，应返回 200
	w.WriteHeader(200)
}

func RmoteIp(req *http.Request) string {
	remoteAddr := req.RemoteAddr
	if ip := req.Header.Get("XRealIP"); ip != "" {
		remoteAddr = ip
	} else if ip := req.Header.Get("XForwardedFor"); ip != "" {
		remoteAddr = ip
	} else {
		remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
	}
	if remoteAddr == "::1" {
		remoteAddr = "127.0.0.1"
	}
	return remoteAddr
}
